# *-* coding: utf-8 *-*
#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================

'''
Created on 20/ago/2011

@author: antstud
'''
import os.path
import datetime

from koro.core.context import Context
from koro.modules.documenti import model
from koro.db import database
#from koro.settings import TEMPLATE_PATH,TEMPLATE_FATTURA,PDF_PATH,TEMPLATE_PREVENTIVO
from koro.modules.magazzino.context import MagazzinoContext
from koro.modules.anagrafiche.context import AziendaContext


class ContatoreContext(object):
    @staticmethod
    def get_next_num(tipo_doc,serie=''):
        db=database.get_instance()
        try:
            contatore=db.query(model.Contatore).filter_by(tipo_documento=tipo_doc,
                                                          serie=serie).one()
        except:
            contatore=model.Contatore()
            contatore.valore=0
            contatore.tipo_documento=tipo_doc
            contatore.serie=serie
            db.save(contatore)#commit
        return contatore.next()
    
    @staticmethod
    def set_next_num(tipo_doc,next_num,serie=''):
        ContatoreContext.set_current_num(tipo_doc,long(next_num)-1,serie)
    
    @staticmethod
    def set_current_num(tipo_doc,current_num,serie=''):
        db=database.get_instance()
        contatore=db.query(model.Contatore).filter_by(tipo_documento=tipo_doc,
                                                      serie=serie).one()
        contatore.valore=current_num
        db.add(contatore)

#===============================================================================
# DocumentiContext
#===============================================================================
class DocumentiContext(Context):
    def __init__(self,context,tipo_documento):
        Context.__init__(self,context)
        self.tipo_documento=tipo_documento
    
#    def get_objects(self,*args,**kwargs):
#        query=database.get_instance().query(self._context).filter_by(fk_tipo_documento=self.tipo_doc)
#        if len(kwargs)>0:
#            query= query.filter_by(**kwargs)
#        if len(args)>0:
#            for a in args:
#                query=query.filter(a)
#        objects=query.all()
#        for item in objects:
#            self._load_doc_generato(item)
#        return objects
    
#    def _load_doc_generato(self,object):
#        if object.fk_documento_generato is None:
#            object.documento_generato=None
#            return
#        query=database.get_instance().query(self._context)#.filter_by(fk_tipo_documento=model.Documento.REG_FATT_FORN)
#        query=query.filter_by(ID=object.fk_documento_generato)
#        object.documento_generato=query.first()
    
    def get_serie(self):
        return self._get_options().SERIE_DOCUMENTI
   
    def update_object(self,obj):
        database.get_instance().validate_and_save(obj)
    
    def get_next_num(self,serie=''):
        serie=self.get_serie()
        return ContatoreContext.get_next_num(self.tipo_documento,serie)
        
    def set_next_num(self,next_num,serie=''):
        serie=self.get_serie()
        ContatoreContext.set_next_num(self.tipo_documento, next_num, serie)
    
    def set_current_num(self,current_num,serie=''):
        serie=self.get_serie()
        ContatoreContext.set_current_num(self.tipo_documento, current_num, serie)
    
    def chiudi(self,doc,doc_generato):
        doc.chiudi(doc_generato)
        database.get_instance().commit()
    
    def annulla_chiusura(self,doc_generato):
        query=database.get_instance().query(self._context)
        query=query.filter_by(fk_documento_generato=doc_generato.ID)
        doc=query.first()
        if doc is None:
            return
        doc.fk_documento_generato=None
        doc.documento_generato=None
        doc.chiuso=False
        self.commit()
    
    def stampa(self,obj):
        pass
    
#    def _crea_pdf(self,obj,tipo,template):
#        import ho.pisa as pisa
#        #obj=args[0]        
#        azienda=AziendaContext().get_dati_azienda()#qui c'e' un problema
#        indirizzo=(azienda.get_via(),azienda.get_cap(),azienda.get_citta(),azienda.get_provincia())
#        dati_azienda='<b>{ragione_sociale}</b><br> \
#        {0} - {1} - {2} ({3}) <br> \
#        P.IVA {piva}<br> \
#        C.Fisc. {codfisc}<br> \
#        Mobile:{cellulare} Fax:{fax}<br> \
#        E-Mail:{email}<br> \
#        Web:{sitoweb}'.format(*indirizzo,**azienda.__dict__)
#        c=obj.intestatario
#        indirizzo=(c.get_via(),c.get_cap(),c.get_citta(),c.get_provincia())
#        dati_cliente='{ragione_sociale}<br>{0}<br>{1} {2} {3}<br> \
#        P.IVA:{piva} &nbsp&nbsp&nbsp C.F.: {codfisc}'.format(*indirizzo,**c.__dict__)
#
#        dict_={'dati_azienda':dati_azienda,
#           'numero':obj.numero,
#           'cliente':dati_cliente,
#           'data':datetime.date.today().strftime('%d/%m/%Y'),
#           }
#        classe_riga=('even','odd')
#        template_row='<tr class={classe_riga}> \
#        <td class=prodotto>{codice} - {descrizione}</td> \
#        <td class=prezzo>{prezzo} €</td> \
#        <td class=qta>{quantita}</td> \
#        <td class=totale>{totale_riga} €</td> \
#        <td class=iva>{iva_percentuale}%</td> \
#        </tr>'
#        dettaglio=''
#        for cont,riga in enumerate(obj.dettaglio):
#            riga.classe_riga=classe_riga[cont%2]
#            riga.descrizione=riga.prodotto.descrizione
#            riga.codice=riga.prodotto.codice
#            riga.totale_riga=riga.get_totale()
#            riga.iva_percentuale=riga.get_iva_perc()
#            dettaglio+=template_row.format(**riga.__dict__)
#        dict_['dettaglio']=dettaglio
#        obj.calcola_totali()
#        dict_['totale_imponibile']=obj.totale_imponibile
#        dict_['totale_iva']=obj.totale_iva
#        dict_['totale']=obj.get_totale()        
#        source=os.path.join(TEMPLATE_PATH,template)
#        source_obj=open(source)
#        source=source_obj.read()
#        filename='{0}_{1}_del_{2}.pdf'.format(tipo,obj.numero,obj.data.strftime('%d_%m_%Y'))
#        output_path=os.path.join(PDF_PATH,filename)
#        output=open(output_path,"wb")
#        pdf=pisa.CreatePDF(source.format(**dict_),output)
#        source_obj.close()
#        output.close()
#        if not pdf.err:
##            cmd='{0} {1}'.format(PDF_VIEWER,output_path)
#            #os.system(cmd)
#            return output_path
#        return None
        
        
#===============================================================================
# FattureContext
#===============================================================================
class FattureContext(DocumentiContext):
    def __init__(self):
        DocumentiContext.__init__(self,model.Fattura,model.TipoDocumento.FATTURA)
                
    def save_object(self,obj):
        if not obj.is_pending_object():
            return self.update_object(obj)
        obj.numero=self.get_next_num()        
        database.get_instance().validate_and_save(obj)#esegue commit
        self.set_current_num(obj.numero)
        MagazzinoContext.scarica(obj)#esegue commit TODO:valutare se eseguire commit in scarica
    
    def update_object(self,obj):
        obj.validate()
        MagazzinoContext.aggiorna_scarico(obj)#esegue commit        
    
    def new_object(self):
        doc=self._context()        
        doc.numero=self.get_next_num()
        database.get_instance().add(doc)
        return doc
    
    def delete_object(self,obj):
        database.get_instance().flush()
        database.get_instance().remove(obj)#non esegue commit
        MagazzinoContext.cancella_movimenti(obj)
    
#    def crea_pdf(self, obj):
#        return DocumentiContext._crea_pdf(self, obj, 'fattura', TEMPLATE_FATTURA)
    
    
#===============================================================================
# PreventiviContext
#===============================================================================
class PreventiviContext(DocumentiContext):
    def __init__(self):
        DocumentiContext.__init__(self,model.Preventivo,model.TipoDocumento.PREVENTIVO)        

    def delete_object(self, obj):
        database.get_instance().flush()
        return DocumentiContext.delete_object(self, obj)

    def save_object(self,obj):
        if not obj.is_pending_object():
            return self.update_object(obj)        
        obj.numero=self.get_next_num()
        database.get_instance().validate_and_save(obj)#esegue commit    
        self.set_current_num(obj.numero)
        self.commit()
    
    def update_object(self,obj):
        obj.validate()
        database.get_instance().save(obj)        
    
    def new_object(self):
        doc=self._context()        
        doc.numero=self.get_next_num()
        database.get_instance().add(doc)
        return doc
    
#    def crea_pdf(self,obj):
#        return DocumentiContext._crea_pdf(self, obj, 'preventivo', TEMPLATE_PREVENTIVO)


#===============================================================================
# ArriviMerceContext
#===============================================================================
class ArriviMerceContext(DocumentiContext):
    def __init__(self):
        DocumentiContext.__init__(self,model.ArrivoMerce,model.TipoDocumento.ARRIVO_MERCE)

    def save_object(self,obj):        
        if not obj.is_pending_object():
            return self.update_object(obj)        
        obj.numero=self.get_next_num()
        
        obj.fk_listino=1
        database.get_instance().validate_and_save(obj)#esegue commit    
        self.set_current_num(obj.numero)
        MagazzinoContext.carica(obj)#esegue commit TODO:valutare se eseguire commit in carica
        
        #obj.pending=False
    
    def update_object(self,obj):
        obj.validate()
        obj.fk_listino=1
        MagazzinoContext.aggiorna_carico(obj)#esegue commit
    
    def new_object(self):
        doc=model.ArrivoMerce()
        doc.numero=self.get_next_num()
        doc.fk_listino=1
        database.get_instance().add(doc)
        #doc.numero=doc.ID
        return doc
    
    def delete_object(self,obj):
        database.get_instance().flush()
        database.get_instance().remove(obj)#non esegue commit
        MagazzinoContext.cancella_movimenti(obj)#commit      
        

#===============================================================================
# RegFattFornContext
#===============================================================================
class RegFattFornContext(DocumentiContext):
    def __init__(self):
        DocumentiContext.__init__(self,model.RegFattForn,model.TipoDocumento.REG_FATT_FORN)

    def delete_object(self, obj):
        database.get_instance().flush()
        #aggiorna eventuale arrivo merce
        query=database.get_instance().query(model.ArrivoMerce)
        query=query.filter_by(fk_documento_generato=obj.ID)
        doc=query.first()
        if doc is None:
            return
        doc.fk_documento_generato=None
        doc.documento_generato=None
        doc.chiuso=False
        
        return DocumentiContext.delete_object(self, obj)


    def save_object(self,obj):
        if not obj.is_pending_object():
            return self.update_object(obj)
        
        obj.numero=self.get_next_num()
        database.get_instance().validate_and_save(obj)
        self.set_current_num(obj.numero)
        self.commit()      
        
        #obj.fk_tipo_documento=model.Documento.REG_FATT_FORN
        #obj.numero=0
#        database.get_instance().validate_and_save(obj)
        #obj.numero=obj.ID#ID e numero sono uguali
        #database.get_instance().commit()
    
    def update_object(self,obj):
        database.get_instance().validate_and_save(obj)
    
    def new_object(self):
        doc=model.RegFattForn()
        #doc.fk_tipo_documento=model.Documento.REG_FATT_FORN    
        doc.numero=DocumentiContext.get_next_num(self)
        database.get_instance().add(doc)
        #doc.numero=doc.ID
        return doc
    
#    def delete_object(self,obj):
#        database.get_instance().delete(obj)
    
    def genera_reg_fatt_forn(self,arrivo):
        doc=self.new_object()
        doc.intestatario=arrivo.intestatario
        doc.data=datetime.date.today()
        #doc.codice_listino=arrivo.codice_listino
        doc.dettaglio=arrivo.get_dettaglio_reg_fatt_forn()
        doc.totale_imponibile=arrivo.totale_imponibile
        doc.totale_iva=arrivo.totale_iva
        doc.padre=arrivo
        #self.save_object(doc)
        return doc